package com.common.filter;

import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.common.config.CommonApplicationConfig;
import com.common.configuration.SecurityRequestConfiguration;
import com.common.enums.ApiResult;
import com.common.exception.ErrorException;
import com.common.groovy.adapter.GroovyModelAdapter;
import com.common.handler.HttpMethodHandler;
import com.common.model.SystemApplicationServiceModel;
import com.common.mysql.Where;
import com.common.sevice.SystemApplicationModelService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @Description:
 * @Date: 2025/6/30 20:05
 */
@Component
public class SystemLowCodeFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(SystemLowCodeFilter.class);

    @Autowired
    private SystemApplicationModelService modelService;

    @Autowired
    private List<HttpMethodHandler> httpMethodHandlers;

    @Autowired
    private CommonApplicationConfig config;

    @Autowired
    private SecurityRequestConfiguration securityRequestConfiguration;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<String> lowCodePermitAll = securityRequestConfiguration.getLowCodePermitAll();

        if (ObjectUtils.isEmpty(authentication)){
            if (CollectionUtils.isEmpty(lowCodePermitAll)){
                filterChain.doFilter(request, response);
                return;
            }else {
                boolean filterFlag = Boolean.FALSE;
                for (String lowCodePath : lowCodePermitAll) {
                    RequestMatcher requestMatcher = new AntPathRequestMatcher(lowCodePath);
                    if (requestMatcher.matches(request)){
                        filterFlag = Boolean.TRUE;
                        break;
                    }
                }
                if (!filterFlag){
                    filterChain.doFilter(request, response);
                    return;
                }
            }
        }
        String appId = request.getHeader("Appid");
        if (!StringUtils.hasText(appId)) {
            appId = config.getAppId();
        }
        String requestURI = request.getRequestURI();
        if (!ObjectUtils.isEmpty(appId)) {
            SystemApplicationServiceModel applicationServiceModel = modelService.searchOne(Where.build().field("app_id").equal(appId)
                    .and().field("del_flag").equal(0)
                    .and().field("name").equal(requestURI)
                    .and().field("type").equal("2"));
            if (ObjectUtils.isEmpty(applicationServiceModel)) {
                filterChain.doFilter(request, response);
                return;
            }
            String method = request.getMethod();
            Object result = null;
            try {
                for (HttpMethodHandler httpMethodHandler : httpMethodHandlers) {
                    if (httpMethodHandler.validateMethod(method)) {
                        result = httpMethodHandler.handler(request, response, applicationServiceModel);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                handlerErrorMsg(request, response);
            } finally {
                handlerSuccessMsg(request, response, result);
            }
        }

    }

    private void handlerSuccessMsg(HttpServletRequest request, HttpServletResponse response, Object result) throws IOException {
        JSONObject resResult = JSONUtil.createObj();
        resResult.set("status", 0);
        resResult.set("msg", "操作成功");
        if (result instanceof JSONArray){
            resResult.set("data", ObjectUtils.isEmpty(result) ? JSONUtil.createArray() : result);
        }else {
            resResult.set("data", ObjectUtils.isEmpty(result) ? JSONUtil.createObj() : result);
        }
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write(resResult.toStringPretty());
        writer.flush();
        writer.close();
    }

    private void handlerErrorMsg(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JSONObject resResult = JSONUtil.createObj();
        resResult.set("status", 500);
        resResult.set("msg", "操作失败");
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write(resResult.toStringPretty());
        writer.flush();
        writer.close();
    }
}
